print "Error creating root VBD"
xc.domain_destroy ( dom=id )
sys.exit()
- if xc.vbd_add_extent( dom=id,
- vbd=root_info[0],
- device=root_info[1],
- start_sector=root_info[2],
- nr_sectors=root_info[3] ):
+ if xc.vbd_grow( dom=id,
+ vbd=root_info[0],
+ device=root_info[1],
+ start_sector=root_info[2],
+ nr_sectors=root_info[3] ):
print "Error populating root VBD"
xc.domain_destroy ( dom=id )
sys.exit()
print "Error creating usr VBD"
xc.domain_destroy ( dom=id )
sys.exit()
- if xc.vbd_add_extent( dom=id,
- vbd=usr_info[0],
- device=usr_info[1],
- start_sector=usr_info[2],
- nr_sectors=usr_info[3] ):
+ if xc.vbd_grow( dom=id,
+ vbd=usr_info[0],
+ device=usr_info[1],
+ start_sector=usr_info[2],
+ nr_sectors=usr_info[3] ):
print "Error populating usr VBD"
xc.domain_destroy ( dom=id )
sys.exit()
print "Error creating root VBD"
xc.domain_destroy ( dom=id )
sys.exit()
- if xc.vbd_add_extent( dom=id,
- vbd=root_info[0],
- device=root_info[1],
- start_sector=root_info[2],
- nr_sectors=root_info[3] ):
+ if xc.vbd_grow( dom=id,
+ vbd=root_info[0],
+ device=root_info[1],
+ start_sector=root_info[2],
+ nr_sectors=root_info[3] ):
print "Error populating root VBD"
xc.domain_destroy ( dom=id )
sys.exit()
print "Error creating usr VBD"
xc.domain_destroy ( dom=id )
sys.exit()
- if xc.vbd_add_extent( dom=id,
- vbd=usr_info[0],
- device=usr_info[1],
- start_sector=usr_info[2],
- nr_sectors=usr_info[3] ):
+ if xc.vbd_grow( dom=id,
+ vbd=usr_info[0],
+ device=usr_info[1],
+ start_sector=usr_info[2],
+ nr_sectors=usr_info[3] ):
print "Error populating usr VBD"
xc.domain_destroy ( dom=id )
sys.exit()
int xc_domain_destroy(int xc_handle,
unsigned int domid,
int force);
+int xc_domain_pincpu(int xc_handle,
+ unsigned int domid,
+ int cpu);
int xc_domain_getinfo(int xc_handle,
unsigned int first_domid,
unsigned int max_doms,
unsigned long nr_sectors;
} xc_vbd_t;
+typedef struct {
+ unsigned short real_device;
+ unsigned long start_sector;
+ unsigned long nr_sectors;
+} xc_vbdextent_t;
int xc_vbd_create(int xc_handle,
unsigned int domid,
int xc_vbd_destroy(int xc_handle,
unsigned int domid,
unsigned short vbdid);
-int xc_vbd_add_extent(int xc_handle,
+int xc_vbd_grow(int xc_handle,
+ unsigned int domid,
+ unsigned short vbdid,
+ xc_vbdextent_t *extent);
+int xc_vbd_shrink(int xc_handle,
+ unsigned int domid,
+ unsigned short vbdid);
+int xc_vbd_setextents(int xc_handle,
unsigned int domid,
unsigned short vbdid,
- unsigned short real_device,
- unsigned long start_sector,
- unsigned long nr_sectors);
-int xc_vbd_delete_extent(int xc_handle,
- unsigned int domid,
- unsigned short vbdid,
- unsigned short real_device,
- unsigned long start_sector,
- unsigned long nr_sectors);
+ unsigned int nr_extents,
+ xc_vbdextent_t *extents);
+int xc_vbd_getextents(int xc_handle,
+ unsigned int domid,
+ unsigned short vbdid,
+ unsigned int max_extents,
+ xc_vbdextent_t *extents,
+ int *writeable);
int xc_vbd_probe(int xc_handle,
unsigned int domid,
unsigned int max_vbds,
}
-int xc_vbd_add_extent(int xc_handle,
- unsigned int domid,
- unsigned short vbdid,
- unsigned short real_device,
- unsigned long start_sector,
- unsigned long nr_sectors)
+int xc_vbd_grow(int xc_handle,
+ unsigned int domid,
+ unsigned short vbdid,
+ xc_vbdextent_t *extent)
{
block_io_op_t op;
- op.cmd = BLOCK_IO_OP_VBD_ADD;
- op.u.add_params.domain = domid;
- op.u.add_params.vdevice = vbdid;
- op.u.add_params.extent.device = real_device;
- op.u.add_params.extent.start_sector = start_sector;
- op.u.add_params.extent.nr_sectors = nr_sectors;
+ op.cmd = BLOCK_IO_OP_VBD_GROW;
+ op.u.grow_params.domain = domid;
+ op.u.grow_params.vdevice = vbdid;
+ op.u.grow_params.extent.device = extent->real_device;
+ op.u.grow_params.extent.start_sector = extent->start_sector;
+ op.u.grow_params.extent.nr_sectors = extent->nr_sectors;
return do_block_io_op(xc_handle, &op);
}
-int xc_vbd_delete_extent(int xc_handle,
- unsigned int domid,
- unsigned short vbdid,
- unsigned short real_device,
- unsigned long start_sector,
- unsigned long nr_sectors)
+int xc_vbd_shrink(int xc_handle,
+ unsigned int domid,
+ unsigned short vbdid)
{
block_io_op_t op;
- op.cmd = BLOCK_IO_OP_VBD_REMOVE;
- op.u.add_params.domain = domid;
- op.u.add_params.vdevice = vbdid;
- op.u.add_params.extent.device = real_device;
- op.u.add_params.extent.start_sector = start_sector;
- op.u.add_params.extent.nr_sectors = nr_sectors;
+ op.cmd = BLOCK_IO_OP_VBD_SHRINK;
+ op.u.shrink_params.domain = domid;
+ op.u.shrink_params.vdevice = vbdid;
return do_block_io_op(xc_handle, &op);
}
+int xc_vbd_setextents(int xc_handle,
+ unsigned int domid,
+ unsigned short vbdid,
+ unsigned int nr_extents,
+ xc_vbdextent_t *extents)
+{
+ int i, rc;
+ block_io_op_t op;
+ xen_extent_t *real_extents = NULL;
+
+ if ( nr_extents != 0 )
+ {
+ real_extents = malloc(nr_extents * sizeof(xc_vbdextent_t));
+ if ( (real_extents == NULL) ||
+ (mlock(real_extents, nr_extents * sizeof(xc_vbdextent_t)) != 0) )
+ {
+ if ( real_extents != NULL )
+ free(real_extents);
+ return -ENOMEM;
+ }
+
+ for ( i = 0; i < nr_extents; i++ )
+ {
+ real_extents[i].device = extents[i].real_device;
+ real_extents[i].start_sector = extents[i].start_sector;
+ real_extents[i].nr_sectors = extents[i].nr_sectors;
+ }
+ }
+
+ op.cmd = BLOCK_IO_OP_VBD_SET_EXTENTS;
+ op.u.setextents_params.domain = domid;
+ op.u.setextents_params.vdevice = vbdid;
+ op.u.setextents_params.nr_extents = nr_extents;
+ op.u.setextents_params.extents = real_extents;
+ rc = do_block_io_op(xc_handle, &op);
+
+ if ( real_extents != NULL )
+ {
+ (void)munlock(real_extents, nr_extents * sizeof(xc_vbdextent_t));
+ free(real_extents);
+ }
+
+ return rc;
+}
+
+
+int xc_vbd_getextents(int xc_handle,
+ unsigned int domid,
+ unsigned short vbdid,
+ unsigned int max_extents,
+ xc_vbdextent_t *extents,
+ int *writeable)
+{
+ int i, rc;
+ block_io_op_t op;
+ xen_extent_t *real_extents = malloc(max_extents * sizeof(xc_vbdextent_t));
+
+ if ( (real_extents == NULL) ||
+ (mlock(real_extents, max_extents * sizeof(xc_vbdextent_t)) != 0) )
+ {
+ if ( real_extents != NULL )
+ free(real_extents);
+ return -ENOMEM;
+ }
+
+ op.cmd = BLOCK_IO_OP_VBD_INFO;
+ op.u.info_params.domain = domid;
+ op.u.info_params.vdevice = vbdid;
+ op.u.info_params.maxextents = max_extents;
+ op.u.info_params.extents = real_extents;
+ rc = do_block_io_op(xc_handle, &op);
+
+ (void)munlock(real_extents, max_extents * sizeof(xc_vbdextent_t));
+
+ if ( rc >= 0 )
+ {
+ for ( i = 0; i < op.u.info_params.nextents; i++ )
+ {
+ extents[i].real_device = real_extents[i].device;
+ extents[i].start_sector = real_extents[i].start_sector;
+ extents[i].nr_sectors = real_extents[i].nr_sectors;
+ }
+
+ if ( writeable != NULL )
+ *writeable = !!(op.u.info_params.mode & VBD_MODE_W);
+
+ rc = op.u.info_params.nextents;
+ }
+
+ free(real_extents);
+
+ return rc;
+}
+
+
int xc_vbd_probe(int xc_handle,
unsigned int domid,
unsigned int max_vbds,
return PyInt_FromLong(ret);
}
-static PyObject *pyxc_vbd_add_extent(PyObject *self,
- PyObject *args,
- PyObject *kwds)
+static PyObject *pyxc_vbd_grow(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
- unsigned int dom, vbd, device;
- unsigned long start_sector, nr_sectors;
- int ret;
+ unsigned int dom, vbd;
+ xc_vbdextent_t extent;
+ int ret;
static char *kwd_list[] = { "dom", "vbd", "device",
"start_sector", "nr_sectors", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiill", kwd_list,
- &dom, &vbd, &device,
- &start_sector, &nr_sectors) )
+ &dom, &vbd,
+ &extent.real_device,
+ &extent.start_sector,
+ &extent.nr_sectors) )
return NULL;
- ret = xc_vbd_add_extent(xc->xc_handle, dom, vbd, device,
- start_sector, nr_sectors);
+ ret = xc_vbd_grow(xc->xc_handle, dom, vbd, &extent);
return PyInt_FromLong(ret);
}
-static PyObject *pyxc_vbd_delete_extent(PyObject *self,
- PyObject *args,
- PyObject *kwds)
+static PyObject *pyxc_vbd_shrink(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
- unsigned int dom, vbd, device;
- unsigned long start_sector, nr_sectors;
+ unsigned int dom, vbd;
int ret;
- static char *kwd_list[] = { "dom", "vbd", "device",
- "start_sector", "nr_sectors", NULL };
+ static char *kwd_list[] = { "dom", "vbd", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiill", kwd_list,
- &dom, &vbd, &device,
- &start_sector, &nr_sectors) )
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
+ &dom, &vbd) )
return NULL;
- ret = xc_vbd_delete_extent(xc->xc_handle, dom, vbd, device,
- start_sector, nr_sectors);
+ ret = xc_vbd_shrink(xc->xc_handle, dom, vbd);
+
+ return PyInt_FromLong(ret);
+}
+
+static PyObject *pyxc_vbd_setextents(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ PyObject *list, *dict, *obj;
+
+ unsigned int dom, vbd;
+ xc_vbdextent_t *extents = NULL;
+ int ret, i, nr_extents;
+
+ static char *kwd_list[] = { "dom", "vbd", "extents", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iio", kwd_list,
+ &dom, &vbd, &list) )
+ goto fail;
+
+ if ( (nr_extents = PyList_Size(list)) < 0 )
+ goto fail;
+
+ if ( nr_extents != 0 )
+ {
+ extents = malloc(nr_extents * sizeof(xc_vbdextent_t));
+ if ( extents == NULL )
+ goto fail;
+
+ for ( i = 0; i < nr_extents; i++ )
+ {
+ dict = PyList_GetItem(list, i);
+ if ( !PyDict_Check(dict) )
+ goto fail;
+ if ( ((obj = PyDict_GetItemString(dict, "device")) == NULL) ||
+ !PyInt_Check(obj) )
+ goto fail;
+ extents[i].real_device = (unsigned short)PyInt_AsLong(obj);
+ if ( ((obj = PyDict_GetItemString(dict,"start_sector")) == NULL) ||
+ !PyInt_Check(obj) )
+ goto fail;
+ extents[i].start_sector = PyInt_AsLong(obj);
+ if ( ((obj = PyDict_GetItemString(dict, "nr_sectors")) == NULL) ||
+ !PyInt_Check(obj) )
+ goto fail;
+ extents[i].nr_sectors = PyInt_AsLong(obj);
+ }
+ }
+
+ ret = xc_vbd_setextents(xc->xc_handle, dom, vbd, nr_extents, extents);
+
+ if ( extents != NULL )
+ free(extents);
return PyInt_FromLong(ret);
+
+ fail:
+ if ( extents != NULL )
+ free(extents);
+ return NULL;
+}
+
+#define MAX_EXTENTS 1024
+static PyObject *pyxc_vbd_getextents(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ PyObject *list;
+
+ unsigned int dom, vbd;
+ xc_vbdextent_t *extents;
+ int i, nr_extents, max_extents;
+
+ static char *kwd_list[] = { "dom", "vbd", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
+ &dom, &vbd) )
+ return NULL;
+
+ extents = malloc(MAX_EXTENTS * sizeof(xc_vbdextent_t));
+ if ( extents == NULL )
+ max_extents = 0;
+ else
+ max_extents = MAX_EXTENTS;
+
+ nr_extents = xc_vbd_getextents(xc->xc_handle, dom, vbd, max_extents,
+ extents, NULL);
+
+ if ( nr_extents <= 0 )
+ {
+ list = PyList_New(0);
+ }
+ else
+ {
+ list = PyList_New(nr_extents);
+ for ( i = 0; i < nr_extents; i++ )
+ {
+ PyList_SetItem(
+ list, i,
+ Py_BuildValue("{s:i,s:l,s:l}",
+ "device", extents[i].real_device,
+ "start_sector", extents[i].start_sector,
+ "nr_sectors", extents[i].nr_sectors));
+ }
+ }
+
+ if ( extents != NULL )
+ free(extents);
+
+ return list;
}
static PyObject *pyxc_vbd_probe(PyObject *self,
" vbd [int]: Identifier of the VBD.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
- { "vbd_add_extent",
- (PyCFunction)pyxc_vbd_add_extent,
+ { "vbd_grow",
+ (PyCFunction)pyxc_vbd_grow,
METH_VARARGS | METH_KEYWORDS, "\n"
- "Add an extent to a virtual block device.\n"
+ "Grow a virtual block device by appending a new extent.\n"
" dom [int]: Identifier of domain containing the VBD.\n"
" vbd [int]: Identifier of the VBD.\n"
" device [int]: Identifier of the real underlying block device.\n"
" nr_sectors [int]: Length, in sectors, of this extent.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
- { "vbd_delete_extent",
- (PyCFunction)pyxc_vbd_delete_extent,
+ { "vbd_shrink",
+ (PyCFunction)pyxc_vbd_shrink,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Shrink a virtual block device by deleting its final extent.\n"
+ " dom [int]: Identifier of domain containing the VBD.\n"
+ " vbd [int]: Identifier of the VBD.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "vbd_setextents",
+ (PyCFunction)pyxc_vbd_setextents,
METH_VARARGS | METH_KEYWORDS, "\n"
- "Delete an extent from a virtual block device.\n"
+ "Set all the extent information for a virtual block device.\n"
" dom [int]: Identifier of domain containing the VBD.\n"
" vbd [int]: Identifier of the VBD.\n"
- " device [int]: Identifier of the real underlying block device.\n"
- " start_sector [int]: Real start sector of the extent.\n"
- " nr_sectors [int]: Length, in sectors, of the extent.\n\n"
+ " extents [list of dicts]: Per-extent information.\n"
+ " device [int]: Identifier of the real underlying block device.\n"
+ " start_sector [int]: Real start sector of this extent.\n"
+ " nr_sectors [int]: Length, in sectors, of this extent.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
+ { "vbd_getextents",
+ (PyCFunction)pyxc_vbd_getextents,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Get info on all the extents in a virtual block device.\n"
+ " dom [int]: Identifier of domain containing the VBD.\n"
+ " vbd [int]: Identifier of the VBD.\n\n"
+ "Returns: [list of dicts] per-extent information; empty on error.\n"
+ " device [int]: Identifier of the real underlying block device.\n"
+ " start_sector [int]: Real start sector of this extent.\n"
+ " nr_sectors [int]: Length, in sectors, of this extent.\n" },
+
{ "vbd_probe",
(PyCFunction)pyxc_vbd_probe,
METH_VARARGS | METH_KEYWORDS, "\n"
ret = vbd_create(&op.u.create_params);
break;
- case BLOCK_IO_OP_VBD_ADD:
- /* add an extent to a VBD */
- ret = vbd_add(&op.u.add_params);
+ case BLOCK_IO_OP_VBD_GROW:
+ /* append an extent to a VBD */
+ ret = vbd_grow(&op.u.grow_params);
break;
- case BLOCK_IO_OP_VBD_REMOVE:
- /* remove an extent from a VBD */
- ret = vbd_remove(&op.u.remove_params);
+ case BLOCK_IO_OP_VBD_SHRINK:
+ /* remove teh final extent from a VBD */
+ ret = vbd_shrink(&op.u.shrink_params);
+ break;
+
+ case BLOCK_IO_OP_VBD_SET_EXTENTS:
+ /* a fresh extent list for the given VBD */
+ ret = vbd_setextents(&op.u.setextents_params);
break;
case BLOCK_IO_OP_VBD_DELETE:
/* XXX SMH: crappy 'hash function' .. fix when care. */
#define HSH(_x) ((_x) & (VBD_HTAB_SZ - 1))
+
/*
** Create a new VBD; all this involves is adding an entry to the domain's
** vbd hash table; caller must be privileged.
vbd_t *new_vbd, **pv;
long ret = 0;
- if( !IS_PRIV(current) )
+ if ( unlikely(!IS_PRIV(current)) )
return -EPERM;
- if ( (p = find_domain_by_id(create->domain)) == NULL )
+ if ( unlikely((p = find_domain_by_id(create->domain)) == NULL) )
{
DPRINTK("vbd_create attempted for non-existent domain %d\n",
create->domain);
*pv != NULL;
pv = &(*pv)->next )
{
- if ( (*pv)->vdevice == create->vdevice )
+ if ( unlikely((*pv)->vdevice == create->vdevice) )
{
DPRINTK("vbd_create attempted for already existing vbd\n");
ret = -EINVAL;
break;
}
- new_vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL);
+ if ( unlikely((new_vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL)) == NULL) )
+ {
+ DPRINTK("vbd_create: out of memory\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
new_vbd->vdevice = create->vdevice;
new_vbd->mode = create->mode;
- new_vbd->extents = (xen_extent_le_t *)NULL;
+ new_vbd->extents = NULL;
new_vbd->next = *pv;
*pv = new_vbd;
return ret;
}
-/*
-** Add an extent to an existing VBD; fails if the VBD doesn't exist.
-** Doesn't worry about overlapping extents (e.g. merging etc) for now.
-*/
-long vbd_add(vbd_add_t *add)
+
+/* Grow a VBD by appending a new extent. Fails if the VBD doesn't exist. */
+long vbd_grow(vbd_grow_t *grow)
{
struct task_struct *p;
xen_extent_le_t **px, *x;
vbd_t *v;
long ret = 0;
- if ( !IS_PRIV(current) )
+ if ( unlikely(!IS_PRIV(current)) )
return -EPERM;
- if ( (p = find_domain_by_id(add->domain)) == NULL )
+ if ( unlikely((p = find_domain_by_id(grow->domain)) == NULL) )
{
- DPRINTK("vbd_add attempted for non-existent domain %d\n",
- add->domain);
+ DPRINTK("vbd_grow: attempted for non-existent domain %d\n",
+ grow->domain);
return -EINVAL;
}
spin_lock(&p->vbd_lock);
- for ( v = p->vbdtab[HSH(add->vdevice)]; v != NULL; v = v->next )
- if ( v->vdevice == add->vdevice )
+ for ( v = p->vbdtab[HSH(grow->vdevice)]; v != NULL; v = v->next )
+ if ( v->vdevice == grow->vdevice )
break;
- if ( v == NULL )
+ if ( unlikely(v == NULL) )
{
- DPRINTK("vbd_add; attempted to add extent to non-existent VBD.\n");
+ DPRINTK("vbd_grow: attempted to append extent to non-existent VBD.\n");
ret = -EINVAL;
goto out;
}
- x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL);
- x->extent.device = add->extent.device;
- x->extent.start_sector = add->extent.start_sector;
- x->extent.nr_sectors = add->extent.nr_sectors;
+ if ( unlikely((x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL)) == NULL) )
+ {
+ DPRINTK("vbd_grow: out of memory\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ x->extent.device = grow->extent.device;
+ x->extent.start_sector = grow->extent.start_sector;
+ x->extent.nr_sectors = grow->extent.nr_sectors;
x->next = (xen_extent_le_t *)NULL;
for ( px = &v->extents; *px != NULL; px = &(*px)->next )
return ret;
}
-long vbd_remove(vbd_remove_t *remove)
+
+long vbd_shrink(vbd_shrink_t *shrink)
{
struct task_struct *p;
xen_extent_le_t **px, *x;
if ( !IS_PRIV(current) )
return -EPERM;
- if ( (p = find_domain_by_id(remove->domain)) == NULL )
+ if ( (p = find_domain_by_id(shrink->domain)) == NULL )
{
- DPRINTK("vbd_remove attempted for non-existent domain %d\n",
- remove->domain);
+ DPRINTK("vbd_shrink attempted for non-existent domain %d\n",
+ shrink->domain);
return -EINVAL;
}
spin_lock(&p->vbd_lock);
- for ( v = p->vbdtab[HSH(remove->vdevice)]; v != NULL; v = v->next )
- if ( v->vdevice == remove->vdevice )
+ for ( v = p->vbdtab[HSH(shrink->vdevice)]; v != NULL; v = v->next )
+ if ( v->vdevice == shrink->vdevice )
break;
- if ( v == NULL )
+ if ( unlikely(v == NULL) || unlikely(v->extents == NULL) )
{
- DPRINTK("vbd_remove; attempt to remove ext from non-existent VBD.\n");
+ DPRINTK("vbd_shrink: attempt to remove non-existent extent.\n");
ret = -EINVAL;
goto out;
}
- for ( px = &v->extents; *px != NULL; px = &(*px)->next )
- if ( (*px)->extent.start_sector == remove->extent.start_sector )
- break;
-
- if ( ((x = *px) == NULL) ||
- (x->extent.nr_sectors != remove->extent.nr_sectors) ||
- (x->extent.device != remove->extent.device) )
+ /* Find the last extent. We now know that there is at least one. */
+ for ( px = &v->extents; (*px)->next != NULL; px = &(*px)->next )
+ continue;
+
+ x = *px;
+ *px = x->next;
+ kfree(x);
+
+ out:
+ spin_unlock(&p->vbd_lock);
+ put_task_struct(p);
+ return ret;
+}
+
+
+long vbd_setextents(vbd_setextents_t *setextents)
+{
+ struct task_struct *p;
+ xen_extent_t e;
+ xen_extent_le_t *new_extents, *x, *t;
+ vbd_t *v;
+ int i;
+ long ret = 0;
+
+ if ( !IS_PRIV(current) )
+ return -EPERM;
+
+ if ( (p = find_domain_by_id(setextents->domain)) == NULL )
+ {
+ DPRINTK("vbd_setextents attempted for non-existent domain %d\n",
+ setextents->domain);
+ return -EINVAL;
+ }
+
+ spin_lock(&p->vbd_lock);
+
+ for ( v = p->vbdtab[HSH(setextents->vdevice)]; v != NULL; v = v->next )
+ if ( v->vdevice == setextents->vdevice )
+ break;
+
+ if ( unlikely(v == NULL) )
{
- DPRINTK("vbd_remove: attempt to remove non-matching extent.\n");
+ DPRINTK("vbd_setextents: attempt to modify non-existent VBD.\n");
ret = -EINVAL;
goto out;
}
- *px = x->next;
- kfree(x);
+ /* Construct the new extent list. */
+ new_extents = NULL;
+ for ( i = setextents->nr_extents; i >= 0; i++ )
+ {
+ if ( unlikely(copy_from_user(&e,
+ &setextents->extents[i],
+ sizeof(e)) != 0) )
+ {
+ DPRINTK("vbd_setextents: copy_from_user failed\n");
+ ret = -EFAULT;
+ goto free_and_out;
+ }
+
+ if ( unlikely((x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL))
+ == NULL) )
+ {
+ DPRINTK("vbd_setextents: out of memory\n");
+ ret = -ENOMEM;
+ goto free_and_out;
+ }
+
+ x->extent = e;
+ x->next = new_extents;
+
+ new_extents = x;
+ }
+
+ /* Delete the old extent list _after_ successfully creating the new. */
+ for ( x = v->extents; x != NULL; x = t )
+ {
+ t = x->next;
+ kfree(x);
+ }
+
+ /* Make the new list visible. */
+ v->extents = new_extents;
out:
spin_unlock(&p->vbd_lock);
put_task_struct(p);
- return ret;
+ return ret;
+
+ free_and_out:
+ /* Failed part-way through the new list. Delete all that we managed. */
+ for ( x = new_extents; x != NULL; x = t )
+ {
+ t = x->next;
+ kfree(x);
+ }
+ goto out;
}
+
long vbd_delete(vbd_delete_t *delete)
{
struct task_struct *p;
extents = info->extents;
for ( x = v->extents; x != NULL; x = x->next )
{
+ if ( info->nextents == info->maxextents )
+ break;
if ( copy_to_user(extents, &x->extent, sizeof(xen_extent_t)) )
{
DPRINTK("vbd_info: copy_to_user failed\n");
goto out;
}
extents++;
- info->nextents++;
+ info->nextents++;
}
out:
* Block I/O trap operations and associated structures.
*/
-#define BLOCK_IO_OP_SIGNAL 0 /* let xen know we have work to do */
+#define BLOCK_IO_OP_SIGNAL 0 /* let xen know we have work to do */
#define BLOCK_IO_OP_RESET 1 /* reset ring indexes on quiescent i/f */
#define BLOCK_IO_OP_RING_ADDRESS 2 /* returns machine address of I/O ring */
#define BLOCK_IO_OP_VBD_CREATE 3 /* create a new VBD for a given domain */
-#define BLOCK_IO_OP_VBD_ADD 4 /* add an extent to a given VBD */
-#define BLOCK_IO_OP_VBD_REMOVE 5 /* remove an extent from a given VBD */
-#define BLOCK_IO_OP_VBD_DELETE 6 /* delete a VBD */
-#define BLOCK_IO_OP_VBD_PROBE 7 /* query VBD information for a domain */
-#define BLOCK_IO_OP_VBD_INFO 8 /* query info about a particular VBD */
+#define BLOCK_IO_OP_VBD_GROW 4 /* append an extent to a given VBD */
+#define BLOCK_IO_OP_VBD_SHRINK 5 /* remove last extent from a given VBD */
+#define BLOCK_IO_OP_VBD_SET_EXTENTS 6 /* provide a fresh extent list for VBD */
+#define BLOCK_IO_OP_VBD_DELETE 7 /* delete a VBD */
+#define BLOCK_IO_OP_VBD_PROBE 8 /* query VBD information for a domain */
+#define BLOCK_IO_OP_VBD_INFO 9 /* query info about a particular VBD */
typedef struct _xen_extent {
u16 device;
- u16 unused; // pad
+ u16 unused;
ulong start_sector;
ulong nr_sectors;
} xen_extent_t;
-
-
#define VBD_MODE_R 0x1
#define VBD_MODE_W 0x2
typedef struct _vbd_create {
- unsigned domain; // create VBD for this domain
- u16 vdevice; // 16 bit id domain will refer to VBD as
- u16 mode; // OR of { VBD_MODE_R , VBD_MODE_W }
+ unsigned domain; /* create VBD for this domain */
+ u16 vdevice; /* id by which dom will refer to VBD */
+ u16 mode; /* OR of { VBD_MODE_R , VBD_MODE_W } */
} vbd_create_t;
-typedef struct _vbd_add {
- unsigned domain; // domain in question
- u16 vdevice; // 16 bit id domain refers to VBD as
- xen_extent_t extent; // the extent to add to this VBD
-} vbd_add_t;
+typedef struct _vbd_grow {
+ unsigned domain; /* domain in question */
+ u16 vdevice; /* 16 bit id domain refers to VBD as */
+ xen_extent_t extent; /* the extent to add to this VBD */
+} vbd_grow_t;
-typedef struct _vbd_remove {
- unsigned domain; // domain in question
- u16 vdevice; // 16 bit id domain refers to VBD as
- xen_extent_t extent; // the extent to remove from this VBD
-} vbd_remove_t;
+typedef struct _vbd_shrink {
+ unsigned domain; /* domain in question */
+ u16 vdevice; /* 16 bit id domain refers to VBD as */
+} vbd_shrink_t;
+typedef struct _vbd_setextents {
+ unsigned domain; /* domain in question */
+ u16 vdevice; /* 16 bit id domain refers to VBD as */
+ u16 nr_extents; /* number of extents in the list */
+ xen_extent_t *extents; /* the extents to add to this VBD */
+} vbd_setextents_t;
typedef struct _vbd_delete {
- unsigned domain; // domain in question
- u16 vdevice; // 16 bit id domain refers to VBD as
+ unsigned domain; /* domain in question */
+ u16 vdevice; /* 16 bit id domain refers to VBD as */
} vbd_delete_t;
#define VBD_PROBE_ALL 0xFFFFFFFF
typedef struct _vbd_probe {
- unsigned domain; // domain in question or VBD_PROBE_ALL
- xen_disk_info_t xdi; // where's our space for VBD/disk info
+ unsigned domain; /* domain in question or VBD_PROBE_ALL */
+ xen_disk_info_t xdi; /* where's our space for VBD/disk info */
} vbd_probe_t;
typedef struct _vbd_info {
/* IN variables */
- unsigned domain; // domain in question
- u16 vdevice; // 16 bit id domain refers to VBD as
- u16 maxextents; // max no. of extents to return info for
- xen_extent_t *extents; // pointer to space for array of extents
+ unsigned domain; /* domain in question */
+ u16 vdevice; /* 16 bit id domain refers to VBD as */
+ u16 maxextents; /* max # of extents to return info for */
+ xen_extent_t *extents; /* pointer to space for extent list */
/* OUT variables */
- u16 nextents; // no of extents in the above
- u16 mode; // VBD_MODE_{READONLY,READWRITE}
+ u16 nextents; /* # extents in the above list */
+ u16 mode; /* VBD_MODE_{READONLY,READWRITE} */
} vbd_info_t;
{
/* no entry for BLOCK_IO_OP_SIGNAL */
/* no entry for BLOCK_IO_OP_RESET */
- unsigned long ring_mfn;
- vbd_create_t create_params;
- vbd_add_t add_params;
- vbd_remove_t remove_params;
- vbd_delete_t delete_params;
- vbd_probe_t probe_params;
- vbd_info_t info_params;
+ unsigned long ring_mfn;
+ vbd_create_t create_params;
+ vbd_grow_t grow_params;
+ vbd_shrink_t shrink_params;
+ vbd_setextents_t setextents_params;
+ vbd_delete_t delete_params;
+ vbd_probe_t probe_params;
+ vbd_info_t info_params;
}
u;
} block_io_op_t;
/*
** include/xeno/vbd.h:
** -- xen internal declarations + prototypes for virtual block devices
-**
*/
+
#ifndef __VBD_H__
#define __VBD_H__
/* an entry in a list of xen_extent's */
typedef struct _xen_extent_le {
- xen_extent_t extent; // an individual extent
- struct _xen_extent_le *next; // and a pointer to the next
+ xen_extent_t extent; /* an individual extent */
+ struct _xen_extent_le *next; /* and a pointer to the next */
} xen_extent_le_t;
** Each domain has a hash table to map from these to the relevant VBD.
*/
typedef struct _vbd {
- unsigned short vdevice; // what the domain refers to this vbd as
- unsigned short mode; // VBD_MODE_{READONLY,READWRITE}
- xen_extent_le_t *extents; // list of xen_extents making up this vbd
- struct _vbd *next; // for chaining in the hash table
+ unsigned short vdevice; /* what the domain refers to this vbd as */
+ unsigned short mode; /* VBD_MODE_{READONLY,READWRITE} */
+ xen_extent_le_t *extents; /* list of xen_extents making up this vbd */
+ struct _vbd *next; /* for chaining in the hash table */
} vbd_t;
-#define VBD_HTAB_SZ 16 // no. of entries in the vbd hash table.
+#define VBD_HTAB_SZ 16 /* # entries in the vbd hash table. */
long vbd_create(vbd_create_t *create_params);
-long vbd_add(vbd_add_t *add_params);
-long vbd_remove(vbd_remove_t *remove_params);
+long vbd_grow(vbd_grow_t *grow_params);
+long vbd_shrink(vbd_shrink_t *shrink_params);
+long vbd_setextents(vbd_setextents_t *setextents_params);
long vbd_delete(vbd_delete_t *delete_params);
long vbd_probe(vbd_probe_t *probe_params);
long vbd_info(vbd_info_t *info_params);
int vbd_translate(phys_seg_t *pseg, struct task_struct *p, int operation);
-
#endif /* __VBD_H__ */